/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package domain;

import common.DomainException;
import java.util.Map;
import common.Observer;
import common.ObserverInterest;
import common.ObserverInterestMap;
import java.util.Set;

/**
 *
 * @author David
 */
public class DomainFacadeImpl implements DomainFacade {

    private Architecture architecture;
    private Structure structure;
    private ObserverInterestMap oim;
    private static DomainFacade facade = new DomainFacadeImpl();

    private DomainFacadeImpl() {
        reset();
    }
    
    public static DomainFacade getInstance(){
        return facade;
    }

    @Override
    public final void reset() {
        this.architecture = new Architecture();
        this.structure = new Structure(this.architecture);
        this.oim = new ObserverInterestMap();
    }
    
    @Override
    public ArchitectureDTO getArchitecture(){
        return ArchitectureMapper.getArchitectureDTO(this.architecture);
    }

    @Override
    public void addLayer(String name, int number) throws DomainException {
        this.architecture.addLayer(name, number);
        this.oim.notifyObservers(ObserverInterest.LAYERS_CHANGED);
    }

    @Override
    public void addAllowedLayerToLayer(String fromLayer, String toLayer) throws DomainException {
        this.architecture.addAllowedLayerToLayer(fromLayer, toLayer);
        this.oim.notifyObservers(ObserverInterest.LAYERS_CHANGED);
    }

    @Override
    public void removeAllowedLayerForLayer(String deleteLayer, String fromLayer) throws DomainException {
        this.architecture.removeAllowedLayerForLayer(deleteLayer, fromLayer);
        oim.notifyObservers(ObserverInterest.LAYERS_CHANGED);
    }

    @Override
    public void removeLayer(String name) {
        this.architecture.removeLayer(name);
        this.oim.notifyObservers(ObserverInterest.LAYERS_CHANGED);
        this.oim.notifyObservers(ObserverInterest.UNITS_CHANGED);
    }

    @Override
    public void addUnitToLayer(String unitName, String type, String layerName) throws DomainException {
        this.architecture.addUnitToLayer(unitName, type, layerName);
        this.oim.notifyObservers(ObserverInterest.UNITS_CHANGED);
    }

    @Override
    public void removeUnitFromLayer(String unitName, String unitType, String layerName) {
        this.architecture.removeUnitFromLayer(unitName, unitType, layerName);
        this.oim.notifyObservers(ObserverInterest.UNITS_CHANGED);
    }

    @Override
    public void setArchitectureAuthor(String name) throws DomainException {
        this.architecture.setAuthor(name);
        this.oim.notifyObservers(ObserverInterest.ARCHITECTURE_CHANGED);
    }

    @Override
    public void setArchitectureName(String name) throws DomainException {
        this.architecture.setName(name);
        this.oim.notifyObservers(ObserverInterest.ARCHITECTURE_CHANGED);
    }

    @Override
    public void setStructureAuthor(String name) throws DomainException {
        this.structure.setAuthor(name);
        this.oim.notifyObservers(ObserverInterest.STRUCTURE_CHANGED);
    }

    @Override
    public void setStructureName(String name) throws DomainException {
        this.structure.setName(name);
        this.oim.notifyObservers(ObserverInterest.STRUCTURE_CHANGED);
    }

    @Override
    public String getArchitectureName() {
        return this.architecture.getName();
    }

    @Override
    public String getArchitectureAuthor() {
        return this.architecture.getAuthor();
    }

    @Override
    public String getStructureName() {
        return this.structure.getName();
    }

    @Override
    public String getStructureAuthor() {
        return this.structure.getAuthor();
    }

    @Override
    public Map<String, Layer> getLayerMap() {
        return architecture.getLayerMap();
    }

    @Override
    public boolean removeObserver(Observer observer) {
        return oim.remove(observer);
    }

    @Override
    public void addObserver(Observer observer, ObserverInterest interest) {
        this.oim.put(interest, observer);
    }

    @Override
    public Set<UnitTypeDTO> getUnitTypes() {
        return UnitTypeMapper.getUnitTypeDTOList();
    }

    @Override
    public StructureDTO getStructure() {
        return StructureMapper.getStructureDTO(structure);
    }
}
